const express = require('express');
const router = express.Router();
const readData = require('../../db/module/readData');

// 基础算法配置（可调整）
const BASE_ALGORITHM_CONFIG = {
    hotWeight: 0.3,           // 基础热号权重
    coldWeight: 0.1,          // 基础冷号权重
    recentWeight: 0.1,        // 基础近期号码权重
    consecutiveWeight: 0.2,   // 基础连号权重
    obliqueWeight: 0.1,       // 基础斜连号权重
    repeatWeight: 0.2         // 基础重号权重
};

/**
 * 工具函数：强制转为数字（彻底杜绝字符串）
 */
const forceToNumber = (val) => {
    if (typeof val === 'boolean') return null;
    const num = Number(val);
    return typeof num === 'number' && !isNaN(num) && isFinite(num) ? num : null;
};

/**
 * 工具函数：验证号码有效性（整数+区间内）
 */
const isValidNumber = (num, min, max) => {
    return typeof num === 'number' && num >= min && num <= max && !isNaN(num) && isFinite(num) && Number.isInteger(num);
};

/**
 * 工具函数：数字格式化（小于10补0，返回字符串）
 */
const formatNumber = (num) => {
    return num < 10 ? `0${num}` : String(num);
};

/**
 * 生成智能号码接口
 */
router.post('/generateRandomNumbers', async (req, res) => {
    try {
        const { type } = req.body;
        
        // 1. 验证彩种合法性
        const lotteryTypeResult = await readData({ code: type }, 'lotteryTypes');
        if (lotteryTypeResult.data.length === 0) {
            return res.send({ code: 400, msg: '无效的彩票类型' });
        }
        const lotteryConfig = lotteryTypeResult.data[0];

        // 2. 生成号码（前区必生成，后区按需生成）
        const frontNumbers = await generateNumbersByType(
            'front',
            lotteryConfig.front,
            type
        );
        const backNumbers = lotteryConfig.back && lotteryConfig.hasBack
            ? await generateNumbersByType('back', lotteryConfig.back, type)
            : [];

        // 3. 格式化输出（小于10补0，转字符串）
        const formattedFront = frontNumbers.map(formatNumber);
        const formattedBack = backNumbers.map(formatNumber);

        res.send({
            code: 20000,
            data: {
                front: formattedFront,
                back: formattedBack,
                type: type,
                lotteryName: lotteryConfig.name
            }
        });
    } catch (error) {
        res.send({ code: 50000, msg: error.message });
    }
});

/**
 * 获取统计数据接口
 */
router.post('/getStatistics', async (req, res) => {
    try {
        const { type } = req.body;
        
        // 验证彩种合法性
        const lotteryTypeResult = await readData({ code: type }, 'lotteryTypes');
        if (lotteryTypeResult.data.length === 0) {
            return res.send({ code: 400, msg: '无效的彩票类型' });
        }
        const lotteryConfig = lotteryTypeResult.data[0];

        const stats = await calculateStatistics(type, lotteryConfig);
        res.send({ code: 20000, data: stats });
    } catch (error) {
        res.send({ code: 50000, msg: error.message });
    }
});

/**
 * 按区域类型（前区/后区）生成号码
 */
async function generateNumbersByType(areaType, areaConfig, lotteryType) {
    const { count, min, max, allowDuplicates } = areaConfig;
    const historyData = await getCleanHistoryData(lotteryType, areaType, min, max);
    const hasEnoughHistory = historyData.length > 10;

    // 生成号码（智能/基础随机）
    const numbers = hasEnoughHistory
        ? await generateIntelligentNumbers(count, min, max, allowDuplicates, historyData) // 异步计算动态权重
        : generateBasicRandomNumbers(count, min, max, allowDuplicates);

    // 校验清洗（确保合规）
    return validateAndFixNumbers(numbers, count, min, max, allowDuplicates);
}

/**
 * 基础随机号码生成（保证均匀分布）
 */
function generateBasicRandomNumbers(count, min, max, allowDuplicates) {
    const numbers = [];
    const usedSet = new Set();
    const range = max - min + 1;
    const segments = Math.min(5, range); // 最多分5段，确保分布均匀
    const segmentSize = Math.ceil(range / segments);
    const filledSegments = new Set(); // 记录已填充的区间

    if (allowDuplicates) {
        // 允许重复：按区间均匀生成
        while (numbers.length < count) {
            const segmentIdx = Math.floor(Math.random() * segments);
            const segmentMin = min + segmentIdx * segmentSize;
            const segmentMax = Math.min(segmentMin + segmentSize - 1, max);
            const randomNum = Math.floor(Math.random() * (segmentMax - segmentMin + 1)) + segmentMin;
            numbers.push(randomNum);
        }
    } else {
        // 不允许重复：先按区间各选1个，再补剩余
        // 步骤1：每个区间至少选1个（确保分布）
        while (filledSegments.size < segments && usedSet.size < count) {
            const segmentIdx = Math.floor(Math.random() * segments);
            if (filledSegments.has(segmentIdx)) continue;
            
            const segmentMin = min + segmentIdx * segmentSize;
            const segmentMax = Math.min(segmentMin + segmentSize - 1, max);
            const availableNums = [];
            for (let num = segmentMin; num <= segmentMax; num++) {
                if (!usedSet.has(num)) availableNums.push(num);
            }

            if (availableNums.length > 0) {
                const randomNum = availableNums[Math.floor(Math.random() * availableNums.length)];
                usedSet.add(randomNum);
                filledSegments.add(segmentIdx);
            }
        }

        // 步骤2：补充剩余号码
        while (usedSet.size < count) {
            const randomNum = Math.floor(Math.random() * (max - min + 1)) + min;
            if (!usedSet.has(randomNum)) usedSet.add(randomNum);
        }

        numbers.push(...usedSet);
        numbers.sort((a, b) => a - b);
    }

    return numbers;
}

/**
 * 智能号码生成（算法优化核心）
 */
async function generateIntelligentNumbers(count, min, max, allowDuplicates, historyData) {
    // 1. 分析历史数据（新增高频连号、重号率等）
    const analysis = analyzeHistoryData(historyData, min, max);
    const {
        hotNumbers, coldNumbers, recentNumbers,
        repeatNumbers, obliqueNumbers, allNumbers,
        highFreqConsecutivePairs, repeatRate
    } = analysis;

    // 2. 动态调整权重（根据历史数据特征）
    const dynamicConfig = adjustWeightsByHistory(repeatRate, historyData.length);
    const weightSum = Object.values(dynamicConfig).reduce((a, b) => a + b, 0);
    const targetCounts = Object.fromEntries(
        Object.entries(dynamicConfig).map(([key, weight]) => 
            [key, Math.max(0, Math.round(count * (weight / weightSum)))]
        )
    );

    const selectedNumbers = [];
    const usedSet = new Set();
    const range = max - min + 1;
    const segments = Math.min(5, range); // 分区间确保分布均匀
    const segmentSize = Math.ceil(range / segments);
    const filledSegments = new Set(); // 记录已填充区间

    // 3. 按权重选择号码（优先高频特征）
    // 3.1 重号（动态权重）
    selectAndAddNumbers(
        repeatNumbers, 
        targetCounts.repeatWeight, 
        selectedNumbers, 
        usedSet, 
        allowDuplicates, 
        min, 
        max,
        filledSegments,
        segments,
        segmentSize
    );

    // 3.2 热号（优先高频热号）
    selectAndAddNumbers(
        hotNumbers, 
        targetCounts.hotWeight, 
        selectedNumbers, 
        usedSet, 
        allowDuplicates, 
        min, 
        max,
        filledSegments,
        segments,
        segmentSize
    );

    // 3.3 近期号码
    selectAndAddNumbers(
        recentNumbers, 
        targetCounts.recentWeight, 
        selectedNumbers, 
        usedSet, 
        allowDuplicates, 
        min, 
        max,
        filledSegments,
        segments,
        segmentSize
    );

    // 3.4 冷号（控制比例，避免过多）
    selectAndAddNumbers(
        coldNumbers, 
        targetCounts.coldWeight, 
        selectedNumbers, 
        usedSet, 
        allowDuplicates, 
        min, 
        max,
        filledSegments,
        segments,
        segmentSize
    );

    // 3.5 斜连号（新增间隔斜连）
    selectAndAddNumbers(
        obliqueNumbers, 
        targetCounts.obliqueWeight, 
        selectedNumbers, 
        usedSet, 
        allowDuplicates, 
        min, 
        max,
        filledSegments,
        segments,
        segmentSize
    );

    // 4. 连号生成（优先高频连号组合）
    const consecutiveTarget = allowDuplicates ? Math.floor(targetCounts.consecutiveWeight * 0.5) : targetCounts.consecutiveWeight;
    if (consecutiveTarget > 0 && selectedNumbers.length < count) {
        const needed = Math.min(consecutiveTarget, count - selectedNumbers.length);
        const consecutiveNums = generateHighFreqConsecutiveNumbers(
            highFreqConsecutivePairs,
            allNumbers,
            usedSet,
            needed,
            min,
            max,
            allowDuplicates
        );
        consecutiveNums.forEach(num => {
            if (selectedNumbers.length < count) {
                selectedNumbers.push(num);
                usedSet.add(num);
                // 记录号码所在区间
                const segmentIdx = Math.floor((num - min) / segmentSize);
                filledSegments.add(segmentIdx);
            }
        });
    }

    // 5. 补充号码（确保分布均匀）
    if (selectedNumbers.length < count) {
        const needed = count - selectedNumbers.length;
        const supplementNums = generateUniformSupplementNumbers(
            allNumbers,
            usedSet,
            needed,
            min,
            max,
            allowDuplicates,
            filledSegments,
            segments,
            segmentSize
        );
        selectedNumbers.push(...supplementNums);
    }

    // 6. 最终处理（去重/排序）
    return allowDuplicates
        ? selectedNumbers.slice(0, count)
        : [...usedSet].sort((a, b) => a - b);
}

/**
 * 选择并添加号码（新增区间均匀性控制）
 */
function selectAndAddNumbers(
    sourceList, 
    targetCount, 
    selectedNumbers, 
    usedSet, 
    allowDuplicates, 
    min, 
    max,
    filledSegments,
    segments,
    segmentSize
) {
    if (targetCount <= 0 || !sourceList.length) return;

    // 过滤有效号码+按出现频率排序（优先高频）
    const validSource = sourceList.filter(num => isValidNumber(num, min, max));
    if (!validSource.length) return;

    // 打乱顺序（保留随机性）
    const shuffled = [...validSource].sort(() => 0.5 - Math.random());

    for (const num of shuffled) {
        if (selectedNumbers.length >= targetCount) break;
        if (!allowDuplicates && usedSet.has(num)) continue;

        // 记录区间，确保分布均匀
        const segmentIdx = Math.floor((num - min) / segmentSize);
        filledSegments.add(segmentIdx);

        selectedNumbers.push(num);
        usedSet.add(num);

        if (selectedNumbers.length >= targetCount) break;
    }
}

/**
 * 历史数据特征分析（算法优化核心）
 */
function analyzeHistoryData(historyData, min, max) {
    const numberCountMap = Array(max + 1).fill(0);
    const allNumbers = Array.from({ length: max - min + 1 }, (_, i) => i + min);
    const recentNumbersSet = new Set();
    const historyNumberSet = new Set();
    const consecutivePairCount = new Map(); // 连号组合频率统计
    const lastDraw = historyData[0];
    const totalDraws = historyData.length;

    // 1. 基础统计（出现次数、近期号码、历史号码）
    historyData.forEach((draw, index) => {
        draw.numbers.forEach(num => {
            if (isValidNumber(num, min, max)) {
                numberCountMap[num]++;
                historyNumberSet.add(num);
                if (index < 5) recentNumbersSet.add(num); // 最近5期为近期号码
            }
        });

        // 2. 连号组合统计（相邻2个号码）
        const sortedNums = [...draw.numbers].sort((a, b) => a - b);
        for (let i = 0; i < sortedNums.length - 1; i++) {
            if (sortedNums[i + 1] === sortedNums[i] + 1) {
                const pairKey = `${sortedNums[i]},${sortedNums[i + 1]}`;
                consecutivePairCount.set(pairKey, (consecutivePairCount.get(pairKey) || 0) + 1);
            }
        }
    });

    // 3. 热冷号动态划分（根据历史数据量调整比例）
    const [hotCutoff, coldCutoff] = calculateHotColdCutoffs(totalDraws, allNumbers.length);
    const sortedNumbers = [...allNumbers].sort((a, b) => numberCountMap[b] - numberCountMap[a]);
    const hotNumbers = sortedNumbers.slice(0, hotCutoff);
    const coldNumbers = sortedNumbers.slice(coldCutoff);

    // 4. 斜连号优化（包含间隔1的斜连：如n-2和n，n和n+2）
    const obliqueNumbers = new Set();
    allNumbers.forEach(num => {
        // 基础斜连（n-1和n+1都出现）
        if (historyNumberSet.has(num - 1) && historyNumberSet.has(num + 1)) {
            obliqueNumbers.add(num);
        }
        // 间隔斜连（n-2和n都出现，或n和n+2都出现）
        if (historyNumberSet.has(num - 2) && historyNumberSet.has(num)) {
            obliqueNumbers.add(num - 1);
        }
        if (historyNumberSet.has(num) && historyNumberSet.has(num + 2)) {
            obliqueNumbers.add(num + 1);
        }
    });

    // 5. 高频连号组合（按出现次数排序）
    const highFreqConsecutivePairs = Array.from(consecutivePairCount.entries())
        .sort((a, b) => b[1] - a[1])
        .map(([pairStr]) => pairStr.split(',').map(Number));

    // 6. 重号率计算（上一期号码在本期的出现比例）
    const repeatRate = calculateRepeatRate(historyData);

    // 7. 重号（上一期有效号码）
    const repeatNumbers = lastDraw 
        ? lastDraw.numbers.filter(num => isValidNumber(num, min, max))
        : [];

    return {
        hotNumbers,
        coldNumbers,
        recentNumbers: Array.from(recentNumbersSet),
        repeatNumbers,
        obliqueNumbers: Array.from(obliqueNumbers),
        allNumbers,
        highFreqConsecutivePairs,
        repeatRate
    };
}

/**
 * 动态调整权重（根据历史重号率和数据量）
 */
function adjustWeightsByHistory(repeatRate, totalDraws) {
    const config = { ...BASE_ALGORITHM_CONFIG };

    // 重号权重调整：重号率高则提高权重
    if (repeatRate > 0.3) {
        config.repeatWeight *= 1.2; // 重号率>30%，权重提高20%
    } else if (repeatRate < 0.1) {
        config.repeatWeight *= 0.8; // 重号率<10%，权重降低20%
    }

    // 连号权重调整：数据量少则降低连号权重
    if (totalDraws < 20) {
        config.consecutiveWeight *= 0.7; // 数据<20期，连号权重降低30%
    }

    // 冷号权重调整：数据量多则适当提高冷号权重
    if (totalDraws > 50) {
        config.coldWeight *= 1.1; // 数据>50期，冷号权重提高10%
    }

    return config;
}

/**
 * 计算热冷号划分阈值（动态比例）
 */
function calculateHotColdCutoffs(totalDraws, numberCount) {
    let hotRatio = 0.3;
    let coldRatio = 0.7;

    // 数据量少：热号比例降低，冷号比例提高
    if (totalDraws < 20) {
        hotRatio = 0.2;
        coldRatio = 0.8;
    }
    // 数据量多：热号比例提高，冷号比例降低
    else if (totalDraws > 50) {
        hotRatio = 0.35;
        coldRatio = 0.65;
    }

    const hotCutoff = Math.max(1, Math.floor(numberCount * hotRatio));
    const coldCutoff = Math.min(numberCount - 1, Math.floor(numberCount * coldRatio));

    return [hotCutoff, coldCutoff];
}

/**
 * 计算重号率（上一期号码在本期的出现比例）
 */
function calculateRepeatRate(historyData) {
    if (historyData.length < 2) return 0; // 至少2期数据才计算

    const lastDrawNums = new Set(historyData[0].numbers);
    const prevDrawNums = historyData[1].numbers;
    const repeatCount = prevDrawNums.filter(num => lastDrawNums.has(num)).length;

    return repeatCount / prevDrawNums.length;
}

/**
 * 生成高频连号组合（优先历史高频连号）
 */
function generateHighFreqConsecutiveNumbers(highFreqPairs, allNumbers, usedSet, neededCount, min, max, allowDuplicates) {
    const consecutiveNums = [];
    const validAllNumbers = allNumbers.filter(num => isValidNumber(num, min, max));

    // 1. 优先使用历史高频连号
    for (const pair of highFreqPairs) {
        if (consecutiveNums.length >= neededCount) break;

        for (const num of pair) {
            if (consecutiveNums.length >= neededCount) break;
            if (!allowDuplicates && usedSet.has(num)) continue;

            consecutiveNums.push(num);
            usedSet.add(num);
        }
    }

    // 2. 高频连号不足，补充随机连号
    if (consecutiveNums.length < neededCount) {
        const remainingNeeded = neededCount - consecutiveNums.length;
        const randomConsecutive = generateRandomConsecutiveNumbers(
            validAllNumbers,
            usedSet,
            remainingNeeded,
            min,
            max,
            allowDuplicates
        );
        consecutiveNums.push(...randomConsecutive);
    }

    return consecutiveNums.slice(0, neededCount);
}

/**
 * 生成随机连号（保证区间合理性）
 */
function generateRandomConsecutiveNumbers(allNumbers, usedSet, neededCount, min, max, allowDuplicates) {
    const consecutiveNums = [];
    const availableNums = allowDuplicates
        ? [...allNumbers]
        : allNumbers.filter(num => !usedSet.has(num)).sort((a, b) => a - b);

    // 寻找可用连号区间
    const consecutiveRanges = [];
    for (let i = 0; i < availableNums.length - 1; i++) {
        let currentRange = [availableNums[i]];
        for (let j = i + 1; j < availableNums.length; j++) {
            if (availableNums[j] === availableNums[j - 1] + 1) {
                currentRange.push(availableNums[j]);
            } else {
                break;
            }
        }
        if (currentRange.length >= 2) {
            consecutiveRanges.push(currentRange);
            i += currentRange.length - 1;
        }
    }

    // 从连号区间中选择
    if (consecutiveRanges.length > 0) {
        const shuffledRanges = [...consecutiveRanges].sort(() => 0.5 - Math.random());
        for (const range of shuffledRanges) {
            if (consecutiveNums.length >= neededCount) break;
            for (const num of range) {
                if (consecutiveNums.length >= neededCount) break;
                consecutiveNums.push(num);
                usedSet.add(num);
            }
        }
    }

    // 仍不足，生成新连号
    if (consecutiveNums.length < neededCount) {
        const maxStart = max - neededCount + 1;
        const startNum = Math.floor(Math.random() * (maxStart - min + 1)) + min;
        for (let i = 0; i < neededCount; i++) {
            const num = startNum + i;
            if (isValidNumber(num, min, max)) {
                consecutiveNums.push(num);
                if (!allowDuplicates) usedSet.add(num);
            }
        }
    }

    return consecutiveNums;
}

/**
 * 生成均匀分布的补充号码
 */
function generateUniformSupplementNumbers(allNumbers, usedSet, neededCount, min, max, allowDuplicates, filledSegments, segments, segmentSize) {
    const supplementNums = [];
    const validAllNumbers = allNumbers.filter(num => isValidNumber(num, min, max));
    const availableNums = allowDuplicates
        ? [...validAllNumbers]
        : validAllNumbers.filter(num => !usedSet.has(num));

    // 1. 优先填充未覆盖的区间
    const unusedSegments = [];
    for (let i = 0; i < segments; i++) {
        if (!filledSegments.has(i)) unusedSegments.push(i);
    }

    for (const segmentIdx of unusedSegments) {
        if (supplementNums.length >= neededCount) break;

        const segmentMin = min + segmentIdx * segmentSize;
        const segmentMax = Math.min(segmentMin + segmentSize - 1, max);
        const segmentNums = availableNums.filter(num => num >= segmentMin && num <= segmentMax);

        if (segmentNums.length > 0) {
            const randomNum = segmentNums[Math.floor(Math.random() * segmentNums.length)];
            supplementNums.push(randomNum);
            usedSet.add(randomNum);
            filledSegments.add(segmentIdx);
        }
    }

    // 2. 区间已全覆盖，补充剩余号码
    if (supplementNums.length < neededCount) {
        const shuffled = [...availableNums].sort(() => 0.5 - Math.random());
        for (const num of shuffled) {
            if (supplementNums.length >= neededCount) break;
            if (!allowDuplicates && usedSet.has(num)) continue;

            supplementNums.push(num);
            usedSet.add(num);
        }
    }

    return supplementNums;
}

/**
 * 第一次校验修复（类型+重复+数量）
 */
function validateAndFixNumbers(numbers, count, min, max, allowDuplicates) {
    const validNumbers = numbers.map(forceToNumber).filter(num => isValidNumber(num, min, max));

    const finalNumbers = [];
    const usedSet = new Set();

    if (allowDuplicates) {
        finalNumbers.push(...validNumbers.slice(0, count));
        while (finalNumbers.length < count) {
            const randomNum = Math.floor(Math.random() * (max - min + 1)) + min;
            finalNumbers.push(randomNum);
        }
    } else {
        validNumbers.forEach(num => usedSet.add(num));
        finalNumbers.push(...usedSet);
        while (finalNumbers.length < count) {
            const randomNum = Math.floor(Math.random() * (max - min + 1)) + min;
            if (!usedSet.has(randomNum)) {
                usedSet.add(randomNum);
                finalNumbers.push(randomNum);
            }
        }
        finalNumbers.sort((a, b) => a - b);
    }

    return finalNumbers.slice(0, count);
}

/**
 * 获取清洗后的历史数据
 */
async function getCleanHistoryData(lotteryType, areaType, min, max) {
    try {
        const result = await readData({ type: lotteryType, page: 1, size: 1000000 }, 'lotteryHistory');
        const rawData = result.data || [];

        return rawData.filter(draw => 
            Array.isArray(draw[areaType]) && draw[areaType].length > 0
        ).map(draw => ({
            numbers: draw[areaType]
                .map(forceToNumber)
                .filter(num => isValidNumber(num, min, max))
        })).filter(draw => draw.numbers.length > 0);
    } catch (error) {
        console.warn('获取历史数据失败，使用基础随机生成:', error.message);
        return [];
    }
}

/**
 * 计算统计数据
 */
async function calculateStatistics(lotteryType, lotteryConfig) {
    const historyData = await getCleanHistoryData(lotteryType, 'front', lotteryConfig.front.min, lotteryConfig.front.max);
    const totalDraws = historyData.length;
    const { front, back } = lotteryConfig;

    const frontCounts = Array(front.max + 1).fill(0);
    historyData.forEach(draw => {
        draw.numbers.forEach(num => frontCounts[num]++);
    });

    let backCounts = [];
    if (back && lotteryConfig.hasBack) {
        const backHistory = await getCleanHistoryData(lotteryType, 'back', back.min, back.max);
        backCounts = Array(back.max + 1).fill(0);
        backHistory.forEach(draw => {
            draw.numbers.forEach(num => backCounts[num]++);
        });
    }

    return {
        frontCounts,
        backCounts,
        totalDraws,
        totalFrontNums: totalDraws * front.count,
        totalBackNums: back && lotteryConfig.hasBack ? totalDraws * back.count : 0,
        config: {
            frontMax: front.max,
            backMax: back?.max,
            frontCount: front.count,
            backCount: back?.count,
            frontAllowDuplicates: front.allowDuplicates,
            backAllowDuplicates: back?.allowDuplicates || false,
            name: lotteryConfig.name
        }
    };
}

module.exports = router;